package data_access

import "gorm.io/gorm"

func GetPosts(page, limit int, sort, order string) (posts []Post, total int64, err error) {
	db := DB.Model(&Post{})
	db.Count(&total)
	err = db.Offset((page - 1) * limit).Limit(limit).Find(&posts).Error
	return
}

func GetPostById(id int64) (*Post, error) {
	var post Post
	err := DB.First(&post, id).Error
	return &post, err
}

func IsPostLiked(postId, likerId int64) (bool, error) {
	var count int64
	err := DB.Model(&PLike{}).Where("post_id = ? AND liker_id = ?", postId, likerId).Count(&count).Error
	return count > 0, err
}

func IsPostSaved(postId, saverId int64) (bool, error) {
	var count int64
	err := DB.Model(&PSave{}).Where("post_id = ? AND saver_id = ?", postId, saverId).Count(&count).Error
	return count > 0, err
}

func LikePost(postId, likerId int64) error {
	return DB.Transaction(func(tx *gorm.DB) error {
		if err := tx.Create(&PLike{PostId: postId, LikerId: likerId}).Error; err != nil {
			return err
		}
		return tx.Model(&Post{}).Where("id = ?", postId).UpdateColumn("like_num", gorm.Expr("like_num + ?", 1)).Error
	})
}

func UnlikePost(postId, likerId int64) error {
	return DB.Transaction(func(tx *gorm.DB) error {
		if err := tx.Where("post_id = ? AND liker_id = ?", postId, likerId).Delete(&PLike{}).Error; err != nil {
			return err
		}
		return tx.Model(&Post{}).Where("id = ?", postId).UpdateColumn("like_num", gorm.Expr("like_num - ?", 1)).Error
	})
}

func SavePost(postId, saverId int64) error {
	return DB.Transaction(func(tx *gorm.DB) error {
		if err := tx.Create(&PSave{PostId: postId, SaverId: saverId}).Error; err != nil {
			return err
		}
		return tx.Model(&Post{}).Where("id = ?", postId).UpdateColumn("save_num", gorm.Expr("save_num + ?", 1)).Error
	})
}

func UnsavePost(postId, saverId int64) error {
	return DB.Transaction(func(tx *gorm.DB) error {
		if err := tx.Where("post_id = ? AND saver_id = ?", postId, saverId).Delete(&PSave{}).Error; err != nil {
			return err
		}
		return tx.Model(&Post{}).Where("id = ?", postId).UpdateColumn("save_num", gorm.Expr("save_num - ?", 1)).Error
	})
}

func CreatePost(post *Post) (int64, error) {
	err := DB.Create(post).Error
	return post.Id, err
}

func UpdatePost(post *Post) error {
	return DB.Save(post).Error
}

func DeletePost(id int64) error {
	return DB.Delete(&Post{}, id).Error
}

func GetPostsByUserId(userId int64, page, size int) (posts []Post, total int64, err error) {
	db := DB.Model(&Post{}).Where("writer = ?", userId)
	db.Count(&total)
	err = db.Offset((page - 1) * size).Limit(size).Find(&posts).Error
	return
}
